package bll

import (
  "context"
  "encoding/json"
  "gitlab.local/backend/proto/dto"
  "golang.org/x/sync/errgroup"
  "gorm.io/gorm"
  "manager/auth"
  "manager/client/grpc"
  log "manager/collector/logger"
  "manager/errors"
  "manager/model"
  "manager/model/entity"
  "manager/model/po"
  "manager/store/postgres"
)

// GetBikeLocation 车辆位置
func (a *ebike) GetBikeLocation(sn string) (lo *po.Location) {
  lo = &po.Location{}
  // 进行计算车辆当前位置和设防的位置，触发被盗告警，距离超过100米就告警且车辆在线
  shadowRsp, err := grpc.SCmd.GetShadowAttributes(context.Background(), &dto.GetShadowAttributesRequest{
    DeviceName: sn,
  })
  if err != nil {
    return
  }

  type shadowAttribute struct {
    Location string `json:"location"`
  }
  // 解析影子
  var attribute shadowAttribute
  if shadowRsp.Attribute == "" {
    return
  }

  // 解析
  err = json.Unmarshal([]byte(shadowRsp.Attribute), &attribute)
  if err != nil {
    return
  }

  // 解析
  err = json.Unmarshal([]byte(attribute.Location), &lo)
  if err != nil {
    return
  }
  return
}

// BikeInfo 车辆详情
func (a *ebike) BikeInfo(ctx context.Context, bikeId int64) (info *model.BikeInfo, err error) {
  var (
    bikeInfo   *entity.Ebike
    controlEty *entity.Control
    bikeType   *entity.EbikeType
    eg         *errgroup.Group
  )

  userId, _ := auth.ContextUserID(ctx)
  eg, ctx = errgroup.WithContext(ctx)

  // 车辆信息
  bikeInfo, err = a.iEbike.Find(ctx, bikeId)
  if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
    return nil, errors.EbikeQueryFailed.Error()
  }

  if err != nil {
    log.Error(err)
    return nil, err
  }

  // 门店信息
  storeName := ""
  eg.Go(func() error {
    // 门店
    storeInfo, _ := postgres.Store.Find(ctx, bikeInfo.StoreID)
    if storeInfo != nil {
      storeName = storeInfo.Name
    }
    return nil
  })

  // 中控
  eg.Go(func() error {
    // 中控
    controlEty, _ = a.iControl.Find(ctx, &model.ControlInfoRequest{
      Id: bikeInfo.ControlId,
    })
    return nil
  })

  // 电池
  batteryInfo := &entity.Battery{}
  batterTypeInfo := &entity.BatteryType{}
  eg.Go(func() error {
    // 车型
    batteryInfo, _ = postgres.Battery.Find(ctx, &model.BatteryInfoRequest{
      Id: bikeInfo.BatteryId,
    })

    if batteryInfo != nil && batteryInfo.Id > 0 {
      batterTypeInfo, _ = postgres.BatteryType.Find(ctx, &model.BatteryTypeInfoRequest{
        Id: batteryInfo.BatteryType,
      })
    }
    return nil
  })

  eg.Go(func() error {
    // 车型
    bikeType, err = a.iEbikeType.Find(bikeInfo.TypeID)
    return nil
  })

  // 自定义车辆信息
  var userbikeSettingEty *entity.UserBikeSetting
  eg.Go(func() error {
    userbikeSettingEty, _ = a.iUserBikeSetting.Find(ctx, &model.UserBikeSettingInfoRequest{
      UserId:  &userId,
      EbikeId: &bikeInfo.ID,
    })
    return nil
  })

  // 车辆位置
  var location *po.Location
  eg.Go(func() error {
    location = a.GetBikeLocation(bikeInfo.SNCode)
    return nil
  })

  err = eg.Wait()

  if err != nil {
    log.Error(err)
    return nil, errors.EbikeQueryFailed.Error()
  }

  // 车辆名称
  bikeName := bikeInfo.Name
  if userbikeSettingEty.EbikeName != "" {
    bikeName = userbikeSettingEty.EbikeName
  }
  // 车辆图片
  bikeImage := EbikeType.GetBikeImage(bikeInfo.TypeID, bikeInfo.Color)
  /*	if userbikeSettingEty.EbikeImage != "" {
  	bikeImage = userbikeSettingEty.EbikeImage
  }*/

  // 售卖日期和三包 造假数据
  info = &model.BikeInfo{
    ID:               bikeInfo.ID,
    TypeID:           bikeInfo.TypeID,
    Name:             bikeName,
    Photo:            bikeImage,
    Color:            bikeInfo.Color,
    Status:           bikeInfo.Status,
    FrameCode:        bikeInfo.FrameCode,
    EngineCode:       bikeInfo.EngineCode,
    IsBind:           bikeInfo.IsBind,
    Stock:            bikeInfo.Stock,
    StoreID:          bikeInfo.StoreID,
    ControlId:        bikeInfo.ControlId,
    BatteryId:        bikeInfo.BatteryId,
    BindUsers:        bikeInfo.BindUsers,
    CreatedAt:        bikeInfo.CreatedAt,
    UpdatedAt:        bikeInfo.UpdatedAt,
    SNCode:           bikeInfo.SNCode,
    SocketType:       bikeType.SocketType,
    TypeName:         bikeType.Name,
    Mac:              controlEty.Mac,
    Imei:             controlEty.Imei,
    Iccid:            controlEty.Iccid,
    Imsi:             controlEty.Imsi,
    FirmwareVersion:  controlEty.FirmwareVersion,
    BatteryCode:      batteryInfo.BatteryCode,
    FirmwaresVersion: batteryInfo.FirmwaresVersion,
    BatteryName:      batterTypeInfo.Name,
    Version:          batterTypeInfo.Version,
    Voltage:          batterTypeInfo.Voltage,
    Type:             batterTypeInfo.Type,
    Supplier:         batterTypeInfo.Supplier,
    Capacity:         batterTypeInfo.Capacity,

    StoreName:          storeName,
    BuyTime:            bikeInfo.SaleTime,
    ActivationTime:     bikeInfo.ActivationTime,
    WarrantyPeriodTime: bikeInfo.SaleTime + 365*24*3600,

    Location: *location,
  }

  return
}

func (a *ebike) AppInfo(ctx context.Context, in *model.EbikeBaseRequest) (*model.AppEbikeInfoResponse, error) {
  var (
    err         error
    ety         *entity.Ebike
    out         *model.AppEbikeInfoResponse
    controlEty  *entity.Control
    typeEty     *entity.EbikeType
    userbikeEty *entity.UserEbike
    eg          *errgroup.Group
  )

  userId, _ := auth.ContextUserID(ctx)
  eg, ctx = errgroup.WithContext(ctx)

  ety, err = a.iEbike.Find(ctx, *in.ID)
  if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
    return nil, errors.EbikeQueryFailed.Error()
  }
  if err != nil {
    log.Error(err)
    return nil, err
  }

  // 中控
  eg.Go(func() error {
    // 中控
    controlEty, _ = a.iControl.Find(ctx, &model.ControlInfoRequest{
      Id: ety.ControlId,
    })
    return nil
  })

  // 车型
  eg.Go(func() error {
    // 车型
    typeEty, err = a.iEbikeType.Find(ety.TypeID)
    return err
  })

  eg.Go(func() error {
    // 用户车辆信息
    userbikeEty, err = a.iUserEbike.FindByParameter(ctx, &model.UserEbikeRequest{EbikeID: &ety.ID})
    return nil
  })

  // 自定义车辆信息
  var userbikeSettingEty *entity.UserBikeSetting
  eg.Go(func() error {
    userbikeSettingEty, _ = a.iUserBikeSetting.Find(ctx, &model.UserBikeSettingInfoRequest{
      UserId:  &userId,
      EbikeId: &ety.ID,
    })
    return nil
  })

  err = eg.Wait()

  if err != nil {
    log.Error(err)
    return nil, err
  }

  // 车辆名称
  bikeName := ety.Name
  if userbikeSettingEty.EbikeName != "" {
    bikeName = userbikeSettingEty.EbikeName
  }

  // 车辆图片
  bikeImage := userbikeEty.Photo
  if userbikeSettingEty.EbikeImage != "" {
    bikeImage = userbikeSettingEty.EbikeImage
  }

  // 售卖日期和三包 造假数据
  out = &model.AppEbikeInfoResponse{
    ID:              ety.ID,
    TypeID:          ety.TypeID,
    TypeName:        bikeName,
    Name:            ety.Name,
    Image:           bikeImage,
    SocketType:      typeEty.SocketType,
    Status:          ety.Status,
    FrameCode:       ety.FrameCode,
    EngineCode:      ety.EngineCode,
    Color:           ety.Color,
    IsBind:          ety.IsBind,
    Stock:           ety.Stock,
    FirmwareID:      0, //固件ID
    StoreID:         ety.StoreID,
    CreatedAt:       ety.CreatedAt,
    UpdatedAt:       ety.CreatedAt,
    BindUsers:       ety.BindUsers,
    SNCode:          ety.SNCode,
    Mac:             controlEty.Mac,
    Imei:            controlEty.Imei,
    Iccid:           controlEty.Iccid,
    Imsi:            controlEty.Imsi,
    FirmwareVersion: controlEty.FirmwareVersion,
    IsManager:       userbikeEty.IsManager,
    // 假数据
    // TODO 改掉
    StoreName:          "浙江省杭州市余杭区电摩智电动旗舰店",
    BuyTime:            1681542465,
    ActivationTime:     1681542465,
    WarrantyPeriodTime: 1776236820,
  }

  return out, err

}
